﻿using System.Collections.Generic;
using Microsoft.FxCop.Sdk;

namespace Lephone.FxCop.Rules
{
    public class FileShouldLessThenLimitedLines : BaseIntrospectionRule
    {
        private readonly Dictionary<string, SrcContext> dic;
        private readonly string ErrorMessage;

        public FileShouldLessThenLimitedLines()
            : base("FileShouldLessThenLimitedLines", "Lephone.FxCop.Rules.LephoneRules", typeof(FileShouldLessThenLimitedLines).Assembly)
        {
            dic = new Dictionary<string, SrcContext>();
            ErrorMessage = string.Format("File Should Less Then {0} Lines", AppSettings.FileLinesLimitation);
        }

        public override ProblemCollection Check(string namespaceName, TypeNodeCollection types)
        {
            InitSrcContextDictionary(types);
            foreach (var ctx in dic.Values)
            {
                if (ctx.EndLine > AppSettings.FileLinesLimitation)
                {
                    Problems.Add(new Problem(
                        new Resolution(ErrorMessage), ctx.FileName, 1));
                }
            }
            return Problems;
        }

        private void InitSrcContextDictionary(TypeNodeCollection types)
        {
            foreach (var type in types)
            {
                foreach (var member in type.Members)
                {
                    Method method = member as Method;
                    if (method != null && !string.IsNullOrEmpty(method.SourceContext.FileName))
                    {
                        var n = CommonFunctions.GetSrcContext((Method)member);
                        AddToDictionary(n);
                    }
                    else
                    {
                        AddToDictionary(new SrcContext(member.SourceContext));
                    }
                }
            }
        }

        private void AddToDictionary(SrcContext sc)
        {
            if (!string.IsNullOrEmpty(sc.FileName))
            {
                if (dic.ContainsKey(sc.FileName))
                {
                    var item = dic[sc.FileName];
                    if (sc.StartLine < item.StartLine)
                    {
                        item.StartLine = sc.StartLine;
                    }
                    if (sc.EndLine > item.EndLine)
                    {
                        item.EndLine = sc.EndLine;
                    }
                }
                else
                {
                    dic.Add(sc.FileName, sc);
                }
            }
        }

        public override TargetVisibilities TargetVisibility
        {
            get
            {
                return TargetVisibilities.All;
            }
        }
    }
}
